/* -*- Mode: c; tab-width: 4; c-basic-offset: 4; indent-tabs-mode: nil; -*- */
/*
  RefObject (http://code.google.com/p/refobject/)
  Copyright (C) 2010-2011 MIURA Shirow (sharow)
*/

#include <stdio.h>
#include <stdlib.h>
#include <stdarg.h>
#include <setjmp.h>
#include <cmockery.h>

#include <RefObject/RefObjectAll.h>
#include "test_common.h"


static void
test_RefList_Create0(void **state)
{
    RefObject *list;
    list = RefList_Create();
    assert_true(list != NULL);
    RefObject_DecRef(list);
}

static void
test_RefList_Append0(void **state)
{
    RefObject *list;
    RefObject *value[2];
    RefObject *rvalue;
    list = RefList_Create();
    value[0] = RefInt_Create(0);
    value[1] = RefInt_Create(1);

    assert_true(RefList_GetSize(list) == 0);

    RefList_Append(list, value[0]);
    assert_true(RefList_GetSize(list) == 1);
    rvalue = RefList_GetItem(list, 0);
    assert_true(RefInt_AsInt(rvalue) == 0);

    RefList_Append(list, value[1]);
    assert_true(RefList_GetSize(list) == 2);
    rvalue = RefList_GetItem(list, 0);
    assert_true(RefInt_AsInt(rvalue) == 0);
    rvalue = RefList_GetItem(list, 1);
    assert_true(RefInt_AsInt(rvalue) == 1);

    RefList_Append(list, value[0]);
    assert_true(RefList_GetSize(list) == 3);
    rvalue = RefList_GetItem(list, 0);
    assert_true(RefInt_AsInt(rvalue) == 0);
    rvalue = RefList_GetItem(list, 1);
    assert_true(RefInt_AsInt(rvalue) == 1);
    rvalue = RefList_GetItem(list, 2);
    assert_true(RefInt_AsInt(rvalue) == 0);

    RefObject_DecRef(value[0]);
    RefObject_DecRef(value[1]);
    RefObject_DecRef(list);
}

static void
test_RefList_Insert0(void **state)
{
    RefObject *list;
    RefObject *value[2];
    RefObject *rvalue;
    list = RefList_Create();
    value[0] = RefInt_Create(0);
    value[1] = RefInt_Create(1);

    assert_true(RefList_GetSize(list) == 0);

    RefList_Append(list, value[0]);
    RefList_Append(list, value[1]);
    /* [0, 1] */

    RefList_Insert(list, 0, value[0]);
    /* [0, 0, 1] */
    assert_true(RefList_GetSize(list) == 3);
    rvalue = RefList_GetItem(list, 0);
    assert_true(RefInt_AsInt(rvalue) == 0);
    rvalue = RefList_GetItem(list, 1);
    assert_true(RefInt_AsInt(rvalue) == 0);
    rvalue = RefList_GetItem(list, 2);
    assert_true(RefInt_AsInt(rvalue) == 1);

    RefList_Insert(list, 2, value[1]);
    /* [0, 0, 1, 1] */
    assert_true(RefList_GetSize(list) == 4);
    rvalue = RefList_GetItem(list, 0);
    assert_true(RefInt_AsInt(rvalue) == 0);
    rvalue = RefList_GetItem(list, 1);
    assert_true(RefInt_AsInt(rvalue) == 0);
    rvalue = RefList_GetItem(list, 2);
    assert_true(RefInt_AsInt(rvalue) == 1);
    rvalue = RefList_GetItem(list, 3);
    assert_true(RefInt_AsInt(rvalue) == 1);

    RefObject_DecRef(value[0]);
    RefObject_DecRef(value[1]);
    RefObject_DecRef(list);
}

static void
test_RefList_DeleteItem0(void **state)
{
    RefObject *list;
    RefObject *value[2];
    RefObject *rvalue;
    int result;

    list = RefList_Create();
    value[0] = RefInt_Create(0);
    value[1] = RefInt_Create(1);

    assert_true(RefList_GetSize(list) == 0);

    RefList_Append(list, value[0]);
    RefList_Append(list, value[0]);
    RefList_Append(list, value[1]);
    RefList_Append(list, value[1]);
    /* [0, 0, 1, 1] */

    RefList_DeleteItem(list, 0);
    /* [0, 1, 1] */
    assert_true(RefList_GetSize(list) == 3);
    rvalue = RefList_GetItem(list, 0);
    assert_true(RefInt_AsInt(rvalue) == 0);
    rvalue = RefList_GetItem(list, 1);
    assert_true(RefInt_AsInt(rvalue) == 1);
    rvalue = RefList_GetItem(list, 2);
    assert_true(RefInt_AsInt(rvalue) == 1);

    RefList_DeleteItem(list, 1);
    /* [0, 1] */
    assert_true(RefList_GetSize(list) == 2);
    rvalue = RefList_GetItem(list, 0);
    assert_true(RefInt_AsInt(rvalue) == 0);
    rvalue = RefList_GetItem(list, 1);
    assert_true(RefInt_AsInt(rvalue) == 1);
    rvalue = RefList_GetItem(list, 2);
    assert_true(rvalue == NULL);

    RefList_DeleteItem(list, 1);
    /* [0] */
    assert_true(RefList_GetSize(list) == 1);
    rvalue = RefList_GetItem(list, 0);
    assert_true(RefInt_AsInt(rvalue) == 0);

    result = RefList_DeleteItem(list, 1);
    /* [0] */
    assert_true(RefList_GetSize(list) == 1);
    assert_true(result == 0);   /* fail */

    RefList_DeleteItem(list, 0);
    /* [] */
    assert_true(RefList_GetSize(list) == 0);

    RefObject_DecRef(value[0]);
    RefObject_DecRef(value[1]);
    RefObject_DecRef(list);
}

int
test_RefList(void)
{
    const UnitTest tests[] = {
        unit_test(null_test_success),
        unit_test_setup_teardown(test_RefList_Create0, setup, teardown),
        unit_test_setup_teardown(test_RefList_Append0, setup, teardown),
        unit_test_setup_teardown(test_RefList_Insert0, setup, teardown),
        unit_test_setup_teardown(test_RefList_DeleteItem0, setup, teardown)

    };
    return run_tests(tests);
}
